/*
 * protobufWrapper.h
 *
 *  Created on: 2013. 3. 18.
 *      Author: jaty
 */

#ifndef PROTOBUFWRAPPER_H_
#define PROTOBUFWRAPPER_H_

#include <iostream>
#include "exServer.pb.h"
#include "myMacros.h"

using namespace std;

class Instrument {
        string feedcode;
        uint32_t strike;
        bool isCall;

        double best_bid;
        double best_ask;
        exServer::Instrument *pInst;
        uint32_t base_strike;
        uint32_t max_strike_gap;
        double max_px;

public:
        Instrument() {}
        Instrument(string feedcode, uint32_t strike, bool isCall, double bid, double ask) {
                this->feedcode = feedcode;
                this->strike = strike;
                this->isCall = isCall;
                this->best_bid = bid;
                this->best_ask = ask;
        }
        Instrument(uint32_t base_strike, uint32_t max_strike_gap, double max_px) {
        	generateTestInst(base_strike, max_strike_gap, max_px);
        	pInst = new exServer::Instrument;
        	convertProtoInst();
        }
        ~Instrument() {
        	if(pInst) delete pInst;
        }
        int getProtoInstByteSize() {
        	return pInst->ByteSize();
        }
        string getInstMsgString() {
        	return pInst->SerializeAsString();
        }
        int32_t getInstMsgByteArray(unsigned char *buf) {
        	pInst->SerializeToArray(buf, getProtoInstByteSize());
        	return getProtoInstByteSize();
        }
        void generateTestInst(uint32_t base_strike, uint32_t max_strike_gap, double max_px) {
        	this->base_strike = base_strike;
        	this->max_strike_gap = max_strike_gap;
        	this->max_px = max_px;
                //feedcode = string("TESTCODE|") + getRandomString(3);
                strike =\
                                base_strike + \
                                (uint32_t)(((rand() > RAND_MAX/2)? 1.0 : -1.0) * \
                                (double)max_strike_gap * (double)rand()/(double)RAND_MAX);
                stringstream ss;
                ss << strike;
                feedcode = string("TESTCODE|" + ss.str());
                isCall = (rand() > RAND_MAX/2)? true : false;
                double bid = (double)rand() / (double)RAND_MAX * max_px;
                double ask = (double)rand() / (double)RAND_MAX * max_px;
                bid = (double)(int(bid * 100)) / 100.0;
                ask = (double)(int(ask * 100)) / 100.0;

                if (bid > ask) {
                        best_bid = ask;
                        best_ask = bid;
                } else {
                        best_ask = ask;
                        best_bid = bid;
                }
        }
        void reGenerateRandomInst() {
        	generateTestInst(this->base_strike, this->max_strike_gap, this->max_px);
        	convertProtoInst();
        }
        string getRandomString(int size) {
                char str[size+1];
                TRAVERSE(size) {
                        int n = rand() % 26;
                        str[i] = (char)(n+65);
                }
                str[size] = 0;
                string retStr(str);
                return retStr;
        }
        void convertProtoInst() {
                pInst->set_feedcode(feedcode);
                pInst->set_strike(strike);
                pInst->set_iscall(isCall);
                pInst->set_best_bid(best_bid);
                pInst->set_best_ask(best_ask);
        }
        void printTestInst() {
        	cout << "feedcode= " << pInst->feedcode() << endl;
        	cout << "isCall= " << ((pInst->iscall()==true)? "true" : "false") << endl;
        	cout << "best_bid= " << pInst->best_bid() << endl;
        	cout << "best_ask= " << pInst->best_ask() << endl;
        }
};

class Trade {
private:
	exServer::trade *pTrade_msg;
	uint32_t base_strike;
	uint32_t max_strike_gap;
	double max_px;

public:
	void setTradeMsg(string feedcode, bool isBuy, double price, uint32_t volume) {
		pTrade_msg->set_feedcode(feedcode);
		pTrade_msg->set_isbuy(isBuy);
		pTrade_msg->set_price(price);
		pTrade_msg->set_volume(volume);
	}
    void generateTestTrade(uint32_t base_strike, uint32_t max_strike_gap, double max_px) {
     	this->base_strike = base_strike;
     	this->max_strike_gap = max_strike_gap;
     	this->max_px = max_px;
             //feedcode = string("TESTCODE|") + getRandomString(3);
             uint32_t strike =\
                             base_strike + \
                             (uint32_t)(((rand() > RAND_MAX/2)? 1.0 : -1.0) * \
                             (double)max_strike_gap * (double)rand()/(double)RAND_MAX);
             stringstream ss;
             ss << strike;
             string feedcode = string("TESTCODE|" + ss.str());
             bool isBuy = (rand() > RAND_MAX/2)? true : false;
             double price = (double)rand() / (double)RAND_MAX * max_px;
             uint32_t volume = (double)rand() / (double)RAND_MAX * 5 + 1;
             setTradeMsg(feedcode, isBuy, price, volume);
    }

	Trade(string feedcode, bool isBuy, double price, uint32_t volume) {
		pTrade_msg = new exServer::trade;
		setTradeMsg(feedcode, isBuy, price, volume);
	}
	Trade(uint32_t base_strike, uint32_t max_strike_gap, double max_px) {
		pTrade_msg = new exServer::trade;
		generateTestTrade(base_strike, max_strike_gap, max_px);
	}
	~Trade() {
		delete pTrade_msg;
	}
	int getProtoTradeByteSize() {
		return pTrade_msg->ByteSize();
	}
    int32_t getTradeMsgByteArray(unsigned char *buf) {
    	pTrade_msg->SerializeToArray(buf, getProtoTradeByteSize());
    	return getProtoTradeByteSize();
    }
    exServer::trade *reGenerateTestTrade() {
    	generateTestTrade(base_strike, max_strike_gap, max_px);
    	return pTrade_msg;
    }
	string getTradeMsgString() {
		return pTrade_msg->SerializeAsString();
	}
    void printTestTrade() {
     	cout << "feedcode= " << pTrade_msg->feedcode() << endl;
     	cout << "isCall= " << ((pTrade_msg->isbuy()==true)? "true" : "false") << endl;
     	cout << "price= " << pTrade_msg->price() << endl;
     	cout << "volume= " << pTrade_msg->volume() << endl;
     }
};


#endif /* PROTOBUFWRAPPER_H_ */
